package com.chinasofti.project.common;

import java.io.IOException;
import java.io.InputStream;
import java.net.SocketException;
import java.util.Date;
import java.util.Properties;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.support.PropertiesLoaderUtils;

import com.chinasofti.project.enums.AppResultCode;
import com.chinasofti.project.exceptions.AppException;

/**
 * FTP上传工具
 * 
 * @author Lucas
 *
 */
public class FtpUtil {

	private static Logger logger = LoggerFactory.getLogger(FtpUtil.class);

	private static String FTP_SERVER_ADDRESS;

	private static int FTP_SERVER_PORT;

	private static String FTP_USER;

	private static String FTP_PASSWORD;

	static {
		Properties p;
		try {
			p = PropertiesLoaderUtils.loadAllProperties("app.config.properties");
			FTP_SERVER_ADDRESS = PropConfigUtil.getAndCheck(p, "static.server.ip");
			FTP_SERVER_PORT = Integer.parseInt(PropConfigUtil.getAndCheck(p, "static.server.port"));
			FTP_USER = PropConfigUtil.getAndCheck(p, "static.server.user");
			FTP_PASSWORD = PropConfigUtil.getAndCheck(p, "static.server.pwd");
			logger.info("加载ftp相关配置完成");
			logger.info("\tstatic.server.ip : " + FTP_SERVER_ADDRESS);
			logger.info("\tstatic.server.port : " + FTP_SERVER_PORT);
			logger.info("\tstatic.server.user : " + FTP_USER);
			logger.info("\tstatic.server.pwd : ******");
		} catch (IOException e) {
			logger.error("加载参数失败",e);
		}

	}

	public static String upload(InputStream fileIn, String fileName, String type) throws SocketException, IOException {
		String filePath = null;
		// 连接
		FTPClient ftpClient = connect();

		// 确保文件夹存在
		ensureDir(type, ftpClient);

		// 获取远程文件名
		String removePath = getUploadFileName(fileName, type);
		filePath = getFullFilePath(type, removePath);

		// 上传
		upload(fileIn, ftpClient, removePath);

		// 清理关闭
		cleanUp(fileIn, ftpClient);

		return filePath;

	}

	private static void upload(InputStream fileIn, FTPClient ftpClient, String removePath) throws IOException {
		ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
		if (ftpClient.storeFile(removePath, fileIn)) {
			logger.info("文件" + removePath + "上传成功");
		} else {
			logger.info("文件" + removePath + "上传失败");
		}
	}

	private static String getFullFilePath(String type, String removePath) {
		return type + "/" + removePath;
	}

	private static String getUploadFileName(String fileName, String type) {
		String removePath = type + "_" + DateUtil.formatLong(new Date()) + fileName;
		return removePath;
	}

	private static void cleanUp(InputStream fileIn, FTPClient ftpClient) throws IOException {
		// 关闭文件流
		fileIn.close();
		// 关闭连接
		if (ftpClient != null) {
			ftpClient.logout();
			ftpClient.disconnect();
		}
	}

	private static void ensureDir(String type, FTPClient ftpClient) throws IOException {
		// 指定写入目录,注意:假如指定的目录不存在,会直接上传到根目录,假如存在，就上传到指定路径
		ftpClient.makeDirectory(type);
		ftpClient.changeWorkingDirectory(type);
	}

	private static FTPClient connect() throws SocketException, IOException {
		logger.debug("FTP连接开始...");

		FTPClient ftpClient = new FTPClient();
		ftpClient.setControlEncoding("UTF-8");
		ftpClient.connect(FTP_SERVER_ADDRESS, FTP_SERVER_PORT);
		ftpClient.login(FTP_USER, FTP_PASSWORD);
		int replyCode = ftpClient.getReplyCode();
		ftpClient.setDataTimeout(120000);
		ftpClient.setFileType(FTP.BINARY_FILE_TYPE);// 设置为二进制文件

		if (!FTPReply.isPositiveCompletion(replyCode)) {
			ftpClient.disconnect();
			logger.warn("FTP连接失败,replycode:{}", replyCode);
			throw new AppException(AppResultCode.SYS_ERROR, "FTP无法连接,上传失败,请联系管理员");
		} else {
			logger.info("FTP连接成功");
		}
		return ftpClient;
	}

}
